﻿using System;
using System.Reflection;
using System.Windows.Forms;
using SampleMessages;
using SimpleServiceBus.Bus;
using SimpleServiceBus.Configuration;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Endpoint.Management.Monitoring;
using SimpleServiceBus.Endpoint.Metadata;
using SimpleServiceBus.Endpoints.Msmq;
using SimpleServiceBus.Endpoints.Msmq.Transport;
using SimpleServiceBus.Messages.Management.Monitoring;

namespace SampleConfiglessEndpoint
{
    internal delegate void NotifyDelegate(string message);

    public partial class MainForm : Form
    {
        private IMessagingEndpoint _endpoint;

        public MainForm()
        {
            InitializeComponent();
        }

        public static MainForm Current { get; set; }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Current = this;
            btnStartStop_Click(null, null);
        }

        private void CreateEndpoint()
        {
            MsmqHelper.EnsureQueue("ConfiglessClient");
            MsmqHelper.EnsureQueue("SimpleServiceBus.EndpointMonitor");

            //Create the endpoint
            var epBuilder = new EndpointBuilder<MessagingEndpoint, MsmqTransport>();
            
            //Minimum configuration for endpoint operation
            _endpoint = epBuilder.CreateEndpoint(/*pass IoC wrapper if desired*/);
            epBuilder.Metadata.EndpointID = "SAMPLE_CONFIGLESS_ENDPOINT";
            epBuilder.Metadata.ReturnAddress = "ConfiglessClient";
           
            //Required to be able to subscribe to or send message included in the 
            //desired assembly. This is included so a subscription can be added 
            //for TestPublicationMessage in the SampleMessages.dll
            epBuilder.MessageTypes.RegisterMessageAssembly(Assembly.Load("SampleMessages"), "ManagedClient");
            

            //Required if custom message handlers are in use.
            //This may not be the case if an endpoint is entirley Request/Reply 
            //driven, such as, perhaps, a simple web service bridge.
            epBuilder.MessageHandlers.RegisterMessageHandlerAssembly(GetType().Assembly);



            //Optional configuration for endpoint monitoring
            var perfProbe = CreateStatusProbe();

            //Required configuration for endpoint monitoring if monitoring is used,
            //But endpoint monitoring itself is optional.
            epBuilder.ConfigureEndpointManager("SimpleServiceBus.EndpointMonitor", TimeSpan.FromSeconds(5),
                                               TimeSpan.FromSeconds(10),perfProbe);

            _endpoint.MessageBus.MessageProcessingException += _endpoint_ServiceException;

        }

        void _endpoint_ServiceException(object sender, MessageProcessingErrorEventArgs e)
        {
            Notify("An exception occurred receiving a message (" + e.Exception.Message + "). This was expected, just testing the error handers.");
        }

        private static IEndpointStatusProbe CreateStatusProbe()
        {
            var perfProbe = new PerfCounterProbe
            {
                Name = "Available Memory",
                CanAggregate = true,
                DataType = MeasurementDataType.Numeric,
                UnitOfMeasurement = "MB",
                Category = "Memory",
                Counter = "Available MBytes",
                Instance = String.Empty

            };
            return perfProbe;
        }


        private void StartEndpoint()
        {
            Notify("Starting Endpoint");

            _endpoint.Start();
            
            //We'll subscribe to the test publication
            _endpoint.MessageBus.Subscribe<TestPublicationMessage>();

            Notify("Endpoint Started");
            btnStartStop.Text = "Stop";
        }

        private void StopEndpoint()
        {
            Notify("Stopping Endpoint");

            _endpoint.Stop();

            Notify("Endpoint Stopped");
            btnStartStop.Text = "Start";
        }

        public void Notify(string message)
        {
            if (InvokeRequired)
            {
                NotifyDelegate marshal = Notify;
                BeginInvoke(marshal, message);
            }
            else
            {
                txtStatus.Text += message + Environment.NewLine;
                txtStatus.Refresh();
            }
        }

        private void btnStartStop_Click(object sender, EventArgs e)
        {
            try
            {
                if (_endpoint == null)
                {
                    CreateEndpoint();
                }

                if (_endpoint.IsRunning)
                {
                    StopEndpoint();
                }
                else
                {
                    StartEndpoint();
                }
            }
            catch (Exception ex)
            {
                Notify(ex.Message + Environment.NewLine + ex.StackTrace);
                while (ex.InnerException != null)
                {
                    Notify(ex.InnerException.Message + Environment.NewLine + ex.StackTrace);
                    ex = ex.InnerException;
                }
            }
        }
    }
}